<!DOCTYPE html>












  


<html class="theme-next gemini use-motion" lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">












<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">






















<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=6.4.0" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=6.4.0">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=6.4.0">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=6.4.0">


  <link rel="mask-icon" href="/images/logo.svg?v=6.4.0" color="#222">









<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '6.4.0',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: false,
    fastclick: false,
    lazyload: false,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    algolia: {
      applicationID: 'CSXZLYKER1',
      apiKey: 'ed0357b28f9389115502dc05a109303a',
      indexName: 'wudong.tech',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"我们没有找到任何搜索结果: ${query}","hits_stats":"找到约${hits}条结果（用时${time}ms）"}
    }
  };
</script>


  




  <meta name="description" content="协程学习路径&amp;emsp;&amp;emsp;yield的理解=》yield from的理解=》@asyncio.coroutine的理解=》asyncio和aiohttp的理解">
<meta name="keywords" content="协程,Python">
<meta property="og:type" content="article">
<meta property="og:title" content="Python协程的理解">
<meta property="og:url" content="https://wudong.tech/2022/10/16/协程研究/index.html">
<meta property="og:site_name" content="吴栋的博客">
<meta property="og:description" content="协程学习路径&amp;emsp;&amp;emsp;yield的理解=》yield from的理解=》@asyncio.coroutine的理解=》asyncio和aiohttp的理解">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2022-10-16T06:18:13.109Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Python协程的理解">
<meta name="twitter:description" content="协程学习路径&amp;emsp;&amp;emsp;yield的理解=》yield from的理解=》@asyncio.coroutine的理解=》asyncio和aiohttp的理解">






  <link rel="canonical" href="https://wudong.tech/2022/10/16/协程研究/">



<script type="text/javascript" id="page.configurations">
  CONFIG.page = {
    sidebar: "",
  };
</script>

  <title>Python协程的理解 | 吴栋的博客</title>
  









  <noscript>
  <style type="text/css">
    .use-motion .motion-element,
    .use-motion .brand,
    .use-motion .menu-item,
    .sidebar-inner,
    .use-motion .post-block,
    .use-motion .pagination,
    .use-motion .comments,
    .use-motion .post-header,
    .use-motion .post-body,
    .use-motion .collection-title { opacity: initial; }

    .use-motion .logo,
    .use-motion .site-title,
    .use-motion .site-subtitle {
      opacity: initial;
      top: initial;
    }

    .use-motion {
      .logo-line-before i { left: initial; }
      .logo-line-after i { right: initial; }
    }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">吴栋的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
    
      
        <p class="site-subtitle">非正经菜鸟程序员</p>
      
    
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>



<nav class="site-nav">
  
    <ul id="menu" class="menu">
      
        
        
        
          
          <li class="menu-item menu-item-home">
    <a href="/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-archives">
    <a href="/archives/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-categories">
    <a href="/categories/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-th"></i> <br>分类</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-tags">
    <a href="/tags/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>标签</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-about">
    <a href="/about/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-user"></i> <br>关于</a>
  </li>

      
      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>搜索</a>
        </li>
      
    </ul>
  

  

  
    <div class="site-search">
      
  
  <div class="algolia-popup popup search-popup">
    <div class="algolia-search">
      <div class="algolia-search-input-icon">
        <i class="fa fa-search"></i>
      </div>
      <div class="algolia-search-input" id="algolia-search-input"></div>
    </div>

    <div class="algolia-results">
      <div id="algolia-stats"></div>
      <div id="algolia-hits"></div>
      <div id="algolia-pagination" class="algolia-pagination"></div>
    </div>

    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
  </div>




    </div>
  
</nav>



  



</div>
    </header>

    


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
            

          
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://wudong.tech/2022/10/16/协程研究/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="吴栋">
      <meta itemprop="description" content="技术博客，主攻Java，Python，nodeJS">
      <meta itemprop="image" content="https://wudong-tech.oss-cn-beijing.aliyuncs.com/Hexo%E5%92%8C%E7%A0%81%E4%BA%91%E6%90%AD%E5%BB%BA%E5%B1%9E%E4%BA%8E%E8%87%AA%E5%B7%B1%E7%9A%84%E5%8D%9A%E5%AE%A2/%E5%BD%A4%E5%BD%A41.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="吴栋的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Python协程的理解
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2022-10-16 14:18:11 / 修改时间：14:18:13" itemprop="dateCreated datePublished" datetime="2022-10-16T14:18:11+08:00">2022-10-16</time>
            

            
              

              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Python/" itemprop="url" rel="index"><span itemprop="name">Python</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          
            <span class="post-meta-divider">|</span>
            <span class="post-meta-item-icon">
            <i class="fa fa-eye"></i>
             阅读次数： 
            <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>
            </span>
          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="协程学习路径"><a href="#协程学习路径" class="headerlink" title="协程学习路径"></a>协程学习路径</h1><p>&emsp;&emsp;<a href="#yield">yield的理解</a>=》<a href="#yieldfrom">yield from的理解</a>=》<a href="#asynciocoroutine">@asyncio.coroutine的理解</a>=》<a href="#asyncioaiohttp">asyncio和aiohttp的理解</a></p>
<a id="more"></a>
<h1 id="yield的理解"><a href="#yield的理解" class="headerlink" title="yield的理解"></a><span id="yield">yield的理解</span></h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">def call(k):</span><br><span class="line">    return k*3</span><br><span class="line">def yield_test1(n):</span><br><span class="line">    for i in range(n):</span><br><span class="line">        z = yield call(i)</span><br><span class="line">        print(&quot;z=%s:j=%s&quot; % (z,i))</span><br><span class="line"></span><br><span class="line">n = yield_test1(10)</span><br><span class="line">print(next(n))</span><br><span class="line">print(n.send(11))</span><br></pre></td></tr></table></figure>
<p>执行结果<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">0</span><br><span class="line">z=11:j=0</span><br><span class="line">3</span><br><span class="line"></span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure></p>
<blockquote style="border-left: 4px solid red;background: aqua;">如果一个函数定义中包含yield关键字，那么这个函数就不再是一个普通函数，而是一个generator(生成器)。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">next(n)相当于send(None)，每一执行next或send时，程序遇到yield的时候暂停，并将yield 同行的语句返回（有点类似return）</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">第一次执行next(n)执行到yield call(i)，返回结果0。第二次send(11)将执行，print(“z=%s:j=%s” % (z,i))， yield call(i)，返回结果打印z=11:j=0，返回值3。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">send(11)中send的值将会被z = yield call(i) 中的z接收，所以打印出z=11。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">yield执行到最后抛出StopIteration错误表示无法继续返回下一个值了，本例中for语句自带捕获StopIteration异常，终止循环，其他的情况可能会需要进行异常处理。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">generator(生成器)一般没有return语句，如果任然要写return”123”语句，但是无法正常获得这个值，需要按照以下方法：</blockquote>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">def fib(max):</span><br><span class="line">  n, a, b = 0, 0, 1</span><br><span class="line">  while n &lt; max:</span><br><span class="line">    yield b</span><br><span class="line">    a, b = b, a + b</span><br><span class="line">    n = n + 1</span><br><span class="line">  return &apos;done&apos;</span><br><span class="line"># 捕获Generator的返回值</span><br><span class="line">g = fib(6)</span><br><span class="line">while True:</span><br><span class="line">  try:</span><br><span class="line">    x=next(g)</span><br><span class="line">    print(&apos;g=&apos;,x)</span><br><span class="line">  except StopIteration as e:</span><br><span class="line">    print(&apos;Generrator return value:&apos;, e.value)</span><br><span class="line">    break</span><br></pre></td></tr></table></figure>
<p>执行获取结果：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">g= 1</span><br><span class="line">g= 1</span><br><span class="line">g= 2</span><br><span class="line">g= 3</span><br><span class="line">g= 5</span><br><span class="line">g= 8</span><br><span class="line">Generrator return value: done</span><br></pre></td></tr></table></figure></p>
<h1 id="yield-from的理解"><a href="#yield-from的理解" class="headerlink" title="yield from的理解"></a><span id="yieldfrom">yield from的理解</span></h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">#输出斐波那契數列前 N 个数</span><br><span class="line">def fab3(max):</span><br><span class="line">    n, a, b = 0, 0, 1</span><br><span class="line">    while n &lt; max:</span><br><span class="line">        yield b</span><br><span class="line">        # print b</span><br><span class="line">        a, b = b, a + b</span><br><span class="line">        n = n + 1</span><br><span class="line"></span><br><span class="line">def f_wrapper1(f):</span><br><span class="line">    for g  in f:</span><br><span class="line">        yield g</span><br><span class="line">wrap = f_wrapper1(fab3(5))</span><br><span class="line">for i in wrap:</span><br><span class="line">    print(i,end=&apos; &apos;)</span><br></pre></td></tr></table></figure>
<p>输出结果：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1 1 2 3 5 </span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure></p>
<p>使用yield from修改(使用yield from代替for循环)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">#输出斐波那契數列前 N 个数</span><br><span class="line">def fab3(max):</span><br><span class="line">    n, a, b = 0, 0, 1</span><br><span class="line">    while n &lt; max:</span><br><span class="line">        yield b</span><br><span class="line">        # print b</span><br><span class="line">        a, b = b, a + b</span><br><span class="line">        n = n + 1</span><br><span class="line"></span><br><span class="line">def f_wrapper2(f):</span><br><span class="line">  yield from f  # 注意此处必须是一个可生成对象</span><br><span class="line">wrap = f_wrapper2(fab3(5))</span><br><span class="line">for i in wrap:</span><br><span class="line">  print(i, end=&apos; &apos;)</span><br></pre></td></tr></table></figure></p>
<blockquote style="border-left: 4px solid red;background: aqua;">yield from iterable本质上等于for item in iterable: yield item的缩写版</blockquote><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">print(&apos;yield from包含多个子程序&apos;)</span><br><span class="line">def g(x):</span><br><span class="line">    yield from range(x, 0, -1)</span><br><span class="line">    print(&apos;kk&apos;)</span><br><span class="line">    yield from range(x)</span><br><span class="line">print(list(g(5)))</span><br><span class="line">for g  in g(6):</span><br><span class="line">    print(g,end=&apos;,&apos;)</span><br></pre></td></tr></table></figure><br><br>输出结果：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">yield from包含多个子程序</span><br><span class="line">kk</span><br><span class="line">[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]</span><br><span class="line">6,5,4,3,2,1,kk</span><br><span class="line">0,1,2,3,4,5,</span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure><br><br><blockquote style="border-left: 4px solid red;background: aqua;">利用yield from语句向生成器传送数据。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">传统的生产者-消费者模型是一个线程写消息，一个线程取消息，通过锁机制控制队列和等待，但一不小心就可能死锁。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">如果改用协程，生产者生产消息后，直接通过yield跳转到消费者开始执行，待消费者执行完毕后，换回生产者继续生产，效率极高：</blockquote>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">import time</span><br><span class="line">def consumer_work(len):</span><br><span class="line">  # 读取send传进的数据，并模拟进行处理数据</span><br><span class="line">  print(&quot;writer:&quot;)</span><br><span class="line">  w = &apos;&apos;</span><br><span class="line">  while True:</span><br><span class="line">    w = yield w  # w接收send传进的数据,同时也是返回的数据</span><br><span class="line">    print(&apos;[CONSUMER] Consuming %s...&gt;&gt; &apos;, w)</span><br><span class="line">    w *= len  # 将返回的数据乘以100</span><br><span class="line">    time.sleep(0.1)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def consumer(coro):</span><br><span class="line">  yield from coro  # 将数据传递到协程(生成器)对象中</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def produce(c):</span><br><span class="line">  c.send(None)  # &quot;prime&quot; the coroutine</span><br><span class="line">  for i in range(5):</span><br><span class="line">    print(&apos;[Produce] Producing %s----&apos;, i)</span><br><span class="line">    w = c.send(i)  # 发送完成后进入协程中执行</span><br><span class="line">    print(&apos;[Produce] receive %s----&apos;, w)</span><br><span class="line">  c.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">c1 = consumer_work(100)</span><br><span class="line">produce(consumer(c1))</span><br></pre></td></tr></table></figure>
<p>执行结果：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">writer:</span><br><span class="line">[Produce] Producing %s---- 0</span><br><span class="line">[CONSUMER] Consuming %s...&gt;&gt;  0</span><br><span class="line">[Produce] receive %s---- 0</span><br><span class="line">[Produce] Producing %s---- 1</span><br><span class="line">[CONSUMER] Consuming %s...&gt;&gt;  1</span><br><span class="line">[Produce] receive %s---- 100</span><br><span class="line">[Produce] Producing %s---- 2</span><br><span class="line">[CONSUMER] Consuming %s...&gt;&gt;  2</span><br><span class="line">[Produce] receive %s---- 200</span><br><span class="line">[Produce] Producing %s---- 3</span><br><span class="line">[CONSUMER] Consuming %s...&gt;&gt;  3</span><br><span class="line">[Produce] receive %s---- 300</span><br><span class="line">[Produce] Producing %s---- 4</span><br><span class="line">[CONSUMER] Consuming %s...&gt;&gt;  4</span><br><span class="line">[Produce] receive %s---- 400</span><br><span class="line"></span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure></p>
<h1 id="asyncio-coroutine的理解"><a href="#asyncio-coroutine的理解" class="headerlink" title="@asyncio.coroutine的理解"></a><span id="asynciocoroutine">@asyncio.coroutine的理解</span></h1><blockquote style="border-left: 4px solid red;background: aqua;">asyncio是Python 3.4版本引入的标准库，直接内置了对异步IO的支持。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用，然后把需要执行的协程扔到EventLoop中执行，就实现了异步IO。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">用asyncio实现Hello world代码如下：</blockquote><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">import asyncio</span><br><span class="line"></span><br><span class="line">@asyncio.coroutine</span><br><span class="line">def work(flg, n):</span><br><span class="line">    yield from asyncio.sleep(n)</span><br><span class="line">    print(&quot;word is %s&quot; % flg)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@asyncio.coroutine</span><br><span class="line">def hello(flg, n):</span><br><span class="line">    print(&quot;Hello world! %s&quot; % flg)</span><br><span class="line">    # 异步调用asyncio.sleep(1):</span><br><span class="line">    r = yield from work(flg, n)</span><br><span class="line">    print(&quot;Hello again! %s&quot; % flg)</span><br><span class="line"></span><br><span class="line"># 获取EventLoop:</span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line"># 执行coroutine</span><br><span class="line">tasks = [hello(&quot;zhangsan&quot;, 10), hello(&quot;lisi&quot;, 7)]</span><br><span class="line">loop.run_until_complete(asyncio.wait(tasks))</span><br><span class="line">loop.close()</span><br></pre></td></tr></table></figure><br><br><blockquote style="border-left: 4px solid red;background: aqua;">@asyncio.coroutine把一个generator标记为coroutine类型，然后，我们就把这个coroutine扔到EventLoop中执行。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">上例子中tasks变量中有两个coroutine类型，所以在执行到第一个的asyncio.sleep(n)的时候，不回去等待执行完成，而是开始执行第二个coroutine类型，因此可以实现并发执行。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">为了简化并更好地标识异步IO，从Python3.5开始引入了新的语法async和await，可以让coroutine的代码更简洁易读。请注意，async和await是针对coroutine的新语法，要使用新的语法，只需要做两步替换：<br>1. 把@asyncio.coroutine替换为async；<br>2. 把yield from替换为await。</blockquote>

<h1 id="asyncio和aiohttp的理解"><a href="#asyncio和aiohttp的理解" class="headerlink" title="asyncio和aiohttp的理解"></a><span id="asyncioaiohttp">asyncio和aiohttp的理解</span></h1><blockquote style="border-left: 4px solid red;background: aqua;">asyncio可以实现单线程并发IO操作。如果仅用在客户端，发挥的威力不大。如果把asyncio用在服务器端，例如Web服务器，由于HTTP连接就是IO操作，因此可以用单线程+coroutine实现多用户的高并发支持。</blockquote><br><blockquote style="border-left: 4px solid red;background: aqua;">asyncio实现了TCP、UDP、SSL等协议，aiohttp则是基于asyncio实现的HTTP框架。</blockquote>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">import asyncio</span><br><span class="line"></span><br><span class="line">from aiohttp import web</span><br><span class="line"></span><br><span class="line">async def index(request):</span><br><span class="line">    await asyncio.sleep(0.5)</span><br><span class="line">    return web.Response(body=b&apos;&lt;h1&gt;Index&lt;/h1&gt;&apos;,content_type=&apos;text/html&apos;)</span><br><span class="line"></span><br><span class="line">async def hello(request):</span><br><span class="line">    await asyncio.sleep(0.5)</span><br><span class="line">    text = &apos;&lt;h1&gt;hello, %s!&lt;/h1&gt;&apos; % request.match_info[&apos;name&apos;]</span><br><span class="line">    return web.Response(body=text.encode(&apos;utf-8&apos;),content_type=&apos;text/html&apos;)</span><br><span class="line"></span><br><span class="line">async def init(loop):</span><br><span class="line">    app = web.Application(loop=loop)</span><br><span class="line">    app.router.add_route(&apos;GET&apos;, &apos;/&apos;, index)</span><br><span class="line">    app.router.add_route(&apos;GET&apos;, &apos;/hello/&#123;name&#125;&apos;, hello)</span><br><span class="line">    srv = await loop.create_server(app.make_handler(), &apos;127.0.0.1&apos;, 8000)</span><br><span class="line">    print(&apos;Server started at http://127.0.0.1:8000...&apos;)</span><br><span class="line">    return srv</span><br><span class="line"></span><br><span class="line">loop = asyncio.get_event_loop()</span><br><span class="line">loop.run_until_complete(init(loop))</span><br><span class="line">loop.run_forever()</span><br></pre></td></tr></table></figure>
<h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><ul>
<li><a href="https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432090954004980bd351f2cd4cc18c9e6c06d855c498000" target="_blank">参考文献1：廖雪峰老师官网</a></li>
<li><a href="https://blog.csdn.net/weixin_40907382/article/details/80883034" target="_blank">异步IO (asyncio) 协程</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/27258289" target="_blank">Python Async/Await入门指南</a></li>
<li><a href="https://blog.csdn.net/tinyzhao/article/details/52684473" target="_blank">async with和async for</a></li>
</ul>

      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/协程/" rel="tag"># 协程</a>
          
            <a href="/tags/Python/" rel="tag"># Python</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2018/09/05/JAVA模式-抽象文档模式/" rel="next" title="JAVA模式-抽象文档模式">
                <i class="fa fa-chevron-left"></i> JAVA模式-抽象文档模式
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2022/10/16/Struts2访问jar包内的Action/" rel="prev" title="Struts2访问jar包内的Action问题">
                Struts2访问jar包内的Action问题 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>


  </div>


          </div>
          
  
    <div id="giteementDiv"></div>
    <link rel="stylesheet" href="https://giteement.oss-cn-beijing.aliyuncs.com/default.css">
    <script src="https://giteement.oss-cn-beijing.aliyuncs.com/giteement.browser.js"></script>
    <script>
    var giteement = new Giteement({
      id: 20221016141811,
      owner: 'eillott',
      repo: 'eillott',
      backcall_uri: 'https://wudong.tech',
      oauth_uri: 'https://wudong.tech/token',
      oauth: {
        client_id: '11f02c3f93a28488215ae3c3fda47a5b94d8f60aea0fc1640ca88b353a150f6d',
        client_secret: '2786043fc3856082703cb7f8d63066aabecf5673b6cb4460d7343b860a8ddfd1'
      },
    })
    giteement.render('giteementDiv')
    </script>
  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="https://wudong-tech.oss-cn-beijing.aliyuncs.com/Hexo%E5%92%8C%E7%A0%81%E4%BA%91%E6%90%AD%E5%BB%BA%E5%B1%9E%E4%BA%8E%E8%87%AA%E5%B7%B1%E7%9A%84%E5%8D%9A%E5%AE%A2/%E5%BD%A4%E5%BD%A41.jpg" alt="吴栋">
            
              <p class="site-author-name" itemprop="name">吴栋</p>
              <p class="site-description motion-element" itemprop="description">技术博客，主攻Java，Python，nodeJS</p>
          </div>

          
            <nav class="site-state motion-element">
              
                <div class="site-state-item site-state-posts">
                
                  <a href="/archives/">
                
                    <span class="site-state-item-count">8</span>
                    <span class="site-state-item-name">日志</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-categories">
                  <a href="/categories/index.html">
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">4</span>
                    <span class="site-state-item-name">分类</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-tags">
                  <a href="/tags/index.html">
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">16</span>
                    <span class="site-state-item-name">标签</span>
                  </a>
                </div>
              
            </nav>
          

          

          

          
          

          
          

          
            
          
          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#协程学习路径"><span class="nav-number">1.</span> <span class="nav-text">协程学习路径</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#yield的理解"><span class="nav-number">2.</span> <span class="nav-text">yield的理解</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#yield-from的理解"><span class="nav-number">3.</span> <span class="nav-text">yield from的理解</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#asyncio-coroutine的理解"><span class="nav-number">4.</span> <span class="nav-text">@asyncio.coroutine的理解</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#asyncio和aiohttp的理解"><span class="nav-number">5.</span> <span class="nav-text">asyncio和aiohttp的理解</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#参考资料"><span class="nav-number">6.</span> <span class="nav-text">参考资料</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2022</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">吴栋</span>

  

  
</div>




  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动 v3.9.0</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 – <a class="theme-link" target="_blank" href="https://theme-next.org">NexT.Gemini</a> v6.4.0</div>




        
<div class="busuanzi-count">
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv" title="总访客量">
      <i class="fa fa-user"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
    </span>
  

  
    <span class="site-pv" title="总访问量">
      <i class="fa fa-eye"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
    </span>
  
</div>









        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    
	
    

    
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>














  













  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=6.4.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=6.4.0"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=6.4.0"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=6.4.0"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=6.4.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=6.4.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=6.4.0"></script>



  



  










  




  
  
  
  <link rel="stylesheet" href="/lib/algolia-instant-search/instantsearch.min.css">

  
  
  <script src="/lib/algolia-instant-search/instantsearch.min.js"></script>
  

  <script src="/js/src/algolia-search.js?v=6.4.0"></script>



  

  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  

  
  

  

  

  

  

  

</body>
</html>
